因為上一文章在建立keras.engine.training.Model類別的模型實例時,有稍微敘述和keras.engine.Sequential類別建立實例的差異,這邊要繼續說明在做模型fit的時候有什麼差異的作法。keras.engine.Sequential做fit的運作可以參考之前的文章。
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
inputs = Input(shape=(784,))
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
model = Model(inputs=inputs, outputs=predictions)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(data, labels)
keras.engine.training.Model.fit( ) 的運作是,主要也是跑每個epoch、batch_size設定後的step數量所構成的迴圈,每次跑keras.engine.training.Model.train_step訓練函式。這點和keras.engine.Sequential雷同。
差異在於執行keras.engine.training.Model.train_step訓練函式。
於keras.engine.training.Model.train_step中基本上執行順序就是 keras.engine.training.Model.call -> keras.engine.base_layer.call (每個layer執行call之前的檢查與訓練前處理)。
以本範例,接著會執行模型的keras.engine.functional.call,直接會到keras.engine.functional._run_internal_graph。因為之前建立實體時有執行過keras.engine.functional._init_graph_network 做模型build的動作,已將層的關聯依照遞迴搜尋出後存到自己內建的list中,所以keras.engine.functional._run_internal_graph 這邊會調出此資料依序來呼叫每個 node 層各自的 call 函式。其實各自的 call 函式 就是 每層的父類別 keras.engine.base_layer.call 的呼叫,執行取出設定做對應的處理後,真正再到 keras.layers.core.dense.call 函式中,也就是layer的實體所實作的call函式。layer實體的call函式就會真正執行 input 張量 與 自身權重(kernel) 的內積,再加上bias張量變數,最後再經由所指定的 activation 函式轉換出 output 張量。output 張量再轉變為下一層的 input 張量,重複執行上述動作,直至最後一層的輸出產生為止。
之後的執行運作內容就是和keras.engine.Sequential雷同,計算loss value與update weight。
所以此節與上一節都可以連貫,綜合起來說就是,模型確保keras.engine.sequential._build_graph_network_for_inferred_shape函式 與 keras.engine.functional._init_graph_network 函式 執行過後,就是代表已經build完成可以接續依照每層的設定來計算輸出張量。